#include <iostream>
#include <memory>
#include <string>
#include <grpcpp/grpcpp.h>
#include "service_rpc.grpc.pb.h"
#include "nlohmann/json.hpp"

using json = nlohmann::json;

class GrpcTestClient {
public:
    GrpcTestClient(const std::string& server_address) {
        channel_ = grpc::CreateChannel(server_address, grpc::InsecureChannelCredentials());
        stub_ = service_rpc::ServiceRPC::NewStub(channel_);
        server_address_ = server_address;
    }
    
    bool test_health_check() {
        std::cout << "\n[Test 1] Health Check..." << std::endl;
        
        service_rpc::HealthCheckRequest request;
        service_rpc::HealthCheckResponse response;
        grpc::ClientContext context;
        
        // 设置超时
        std::chrono::system_clock::time_point deadline =
            std::chrono::system_clock::now() + std::chrono::seconds(5);
        context.set_deadline(deadline);
        
        grpc::Status status = stub_->HealthCheck(&context, request, &response);
        
        if (status.ok()) {
            std::cout << "  ✓ Health Check Success!" << std::endl;
            std::cout << "    - Healthy: " << (response.healthy() ? "Yes" : "No") << std::endl;
            std::cout << "    - Service: " << response.service_name() << std::endl;
            std::cout << "    - Version: " << response.version() << std::endl;
            std::cout << "    - Uptime: " << response.uptime_seconds() << " seconds" << std::endl;
            return true;
        } else {
            std::cout << "  ✗ Health Check Failed!" << std::endl;
            std::cout << "    Error Code: " << status.error_code() << std::endl;
            std::cout << "    Error: " << status.error_message() << std::endl;
            return false;
        }
    }
    
    bool test_ping_service() {
        std::cout << "\n[Test 2] Call Service (/api/ping)..." << std::endl;
        
        service_rpc::ServiceRequest request;
        request.set_path("/api/ping");
        request.set_method("GET");
        request.set_request_id("test-request-001");
        request.set_client_ip("127.0.0.1");
        request.set_timestamp(std::chrono::system_clock::now().time_since_epoch().count());
        
        service_rpc::ServiceResponse response;
        grpc::ClientContext context;
        
        std::chrono::system_clock::time_point deadline =
            std::chrono::system_clock::now() + std::chrono::seconds(5);
        context.set_deadline(deadline);
        
        grpc::Status status = stub_->Call(&context, request, &response);
        
        if (status.ok()) {
            std::cout << "  ✓ Service Call Success!" << std::endl;
            std::cout << "    - HTTP Status: " << response.http_status() << std::endl;
            std::cout << "    - Error Code: " << response.error_code() << std::endl;
            std::cout << "    - Message: " << response.message() << std::endl;
            
            if (!response.body().empty()) {
                try {
                    auto body_json = json::parse(response.body());
                    std::cout << "    - Body: " << body_json.dump(2) << std::endl;
                } catch (...) {
                    std::cout << "    - Body (raw): " << response.body() << std::endl;
                }
            }
            return true;
        } else {
            std::cout << "  ✗ Service Call Failed!" << std::endl;
            std::cout << "    Error Code: " << status.error_code() << std::endl;
            std::cout << "    Error: " << status.error_message() << std::endl;
            return false;
        }
    }
    
    bool test_echo_service() {
        std::cout << "\n[Test 3] Call Service (/api/echo)..." << std::endl;
        
        service_rpc::ServiceRequest request;
        request.set_path("/api/echo");
        request.set_method("POST");
        request.set_request_id("test-request-002");
        
        // 设置请求体
        json body_json;
        body_json["message"] = "Hello from gRPC client!";
        body_json["timestamp"] = std::chrono::system_clock::now().time_since_epoch().count();
        std::string body_str = body_json.dump();
        request.set_body(body_str);
        
        service_rpc::ServiceResponse response;
        grpc::ClientContext context;
        
        std::chrono::system_clock::time_point deadline =
            std::chrono::system_clock::now() + std::chrono::seconds(5);
        context.set_deadline(deadline);
        
        grpc::Status status = stub_->Call(&context, request, &response);
        
        if (status.ok()) {
            std::cout << "  ✓ Echo Call Success!" << std::endl;
            std::cout << "    - HTTP Status: " << response.http_status() << std::endl;
            
            if (!response.body().empty()) {
                try {
                    auto body_json = json::parse(response.body());
                    std::cout << "    - Response: " << body_json.dump(2) << std::endl;
                } catch (...) {
                    std::cout << "    - Body (raw): " << response.body() << std::endl;
                }
            }
            return true;
        } else {
            std::cout << "  ✗ Echo Call Failed!" << std::endl;
            std::cout << "    Error: " << status.error_message() << std::endl;
            return false;
        }
    }
    
    bool test_info_service() {
        std::cout << "\n[Test 4] Call Service (/api/info)..." << std::endl;
        
        service_rpc::ServiceRequest request;
        request.set_path("/api/info");
        request.set_method("GET");
        request.set_request_id("test-request-003");
        
        service_rpc::ServiceResponse response;
        grpc::ClientContext context;
        
        std::chrono::system_clock::time_point deadline =
            std::chrono::system_clock::now() + std::chrono::seconds(5);
        context.set_deadline(deadline);
        
        grpc::Status status = stub_->Call(&context, request, &response);
        
        if (status.ok()) {
            std::cout << "  ✓ Info Call Success!" << std::endl;
            
            if (!response.body().empty()) {
                try {
                    auto body_json = json::parse(response.body());
                    std::cout << "    - Service Info: " << body_json.dump(2) << std::endl;
                } catch (...) {
                    std::cout << "    - Body (raw): " << response.body() << std::endl;
                }
            }
            return true;
        } else {
            std::cout << "  ✗ Info Call Failed!" << std::endl;
            std::cout << "    Error: " << status.error_message() << std::endl;
            return false;
        }
    }
    
private:
    std::shared_ptr<grpc::Channel> channel_;
    std::unique_ptr<service_rpc::ServiceRPC::Stub> stub_;
    std::string server_address_;
};

int main(int argc, char* argv[]) {
    std::string server_address = "localhost:9003";
    
    if (argc > 1) {
        server_address = argv[1];
    }
    
    std::cout << "========================================" << std::endl;
    std::cout << "  gRPC Client Test" << std::endl;
    std::cout << "  Server: " << server_address << std::endl;
    std::cout << "========================================" << std::endl;
    
    GrpcTestClient client(server_address);
    
    int passed = 0;
    int failed = 0;
    
    // 执行所有测试
    if (client.test_health_check()) passed++; else failed++;
    if (client.test_ping_service()) passed++; else failed++;
    if (client.test_echo_service()) passed++; else failed++;
    if (client.test_info_service()) passed++; else failed++;
    
    // 输出结果
    std::cout << "\n========================================" << std::endl;
    std::cout << "  Test Results" << std::endl;
    std::cout << "========================================" << std::endl;
    std::cout << "  Passed: " << passed << std::endl;
    std::cout << "  Failed: " << failed << std::endl;
    
    if (failed == 0) {
        std::cout << "\n✅ All tests passed!" << std::endl;
        return 0;
    } else {
        std::cout << "\n❌ Some tests failed!" << std::endl;
        return 1;
    }
}
